#!/bin/sh
# Yes, that's POSIX sh, not bash!

if [ -z "$TMPDIR" ]
then
	TMPDIR=/tmp
fi

REALPATH=$(which realpath)
if [ -z "$REALPATH" ]
then
	REALPATH="readlink -f"
fi

tmpdir=`mktemp -d $TMPDIR/tmp.XXXXXX`
conffile=${tmpdir}/nbd.conf
pidfile=${tmpdir}/nbd.pid
tmpnam=${tmpdir}/nbd.dd
mydir=$(dirname $0)
certdir=$($REALPATH ${mydir}/certs)
cleanup="$2"
PID=""
DELAY=${DELAY:-1}

set -e

cleanup() {
	if [ -f ${pidfile} ]
	then
		kill `cat ${pidfile}` || true
	else
		if [ ! -z "$PID" ]
		then
			kill $PID || true
		fi
	fi
	if [ -z "$cleanup" ]
	then
		rm -rf $tmpdir
	else
		echo "Setup in $tmpdir"
	fi
}

abort() {
	cleanup
	trap - INT
	kill -INT $$
}

trap -- cleanup EXIT
trap -- abort INT

# Create a one-meg device
dd if=/dev/zero of=$tmpnam bs=1024 count=4096 >/dev/null 2>&1

echo $1

case $1 in
	*/cfgsize)
		# Test oversized requests
		cat > ${conffile} <<EOF
[generic]
[export]
	exportname = $tmpnam
EOF
		../../nbd-server -C ${conffile} -p ${pidfile} &
		# -p only works if nbd-server wasn't compiled with -DNOFORK or
		# -DNODAEMON, which I sometimes do for testing and debugging.
		PID=$!
		sleep $DELAY
		./nbd-tester-client -o -N export 127.0.0.1
		retval=$?
	;;
	*/cfg1)
		# Test with export specified in config file
		cat > ${conffile} <<EOF
[generic]
[export]
	exportname = $tmpnam
EOF
		../../nbd-server -C ${conffile} -p ${pidfile} &
		PID=$!
		sleep $DELAY
		./nbd-tester-client -N export 127.0.0.1
		retval=$?
	;;
	*/cfgmulti)
		# Test with multiple exports specified in config file, and
		# testing more options too
		cat >${conffile} <<EOF
[generic]
[export1]
	exportname = $tmpnam
	copyonwrite = true
	listenaddr = 127.0.0.1
[export2]
	exportname = $tmpnam
	readonly = true
	listenaddr = 127.0.0.1
EOF
		../../nbd-server -C ${conffile} -p ${pidfile} &
		PID=$!
		sleep $DELAY
		./nbd-tester-client -N export1 localhost
		retval=$?
		if [ $retval -ne 0 ]
		then
			if [ -f ${pidfile} ]
			then
				kill `cat ${pidfile}`
			else
				kill $PID
			fi
			if [ -z "$2" ]
			then
				rm -rf $tmpdir
			fi
			exit $retval
		fi
		./nbd-tester-client -N export2 localhost
		retval=$?
	;;
	*/cfgnew)
		# Test new-style exports
		cat >${conffile} <<EOF
[generic]
[export1]
	exportname = $tmpnam
EOF
		../../nbd-server -C ${conffile} -p ${pidfile} &
		PID=$!
		sleep $DELAY
		./nbd-tester-client -N export1 localhost
		retval=$?
	;;
	*/write)
		# Test writing
		cat >${conffile} <<EOF
[generic]
[export1]
	exportname = $tmpnam
EOF
		../../nbd-server -C ${conffile} -p ${pidfile} &
		PID=$!
		sleep $DELAY
		./nbd-tester-client -N export1 -w localhost
		retval=$?
	;;
	*/tree)
		# Test treefile mode
		cat >${conffile} <<EOF
[generic]
[export1]
	exportname = ${tmpdir}/nbd.tree
	treefiles = true
	filesize = 4194304
EOF
		../../nbd-server -C ${conffile} -p ${pidfile} &
		PID=$!
		sleep $DELAY
		./nbd-tester-client -N export1 -w localhost
		retval=$?
	;;
	*/rotree)
		# Test treefile mode readonly
		cat >${conffile} <<EOF
[generic]
[export1]
	exportname = ${tmpdir}/nbd.tree
	treefiles = true
	filesize = 4194304
	readonly = true
EOF
		../../nbd-server -C ${conffile} -p ${pidfile} &
		PID=$!
		sleep $DELAY
		./nbd-tester-client -N export1 -w -F localhost
		retval=$?
	;;
	*/flush)
		# Test writes with flush
		cat >${conffile} <<EOF
[generic]
[export1]
	exportname = $tmpnam
	flush = true
	fua = true
	rotational = true
EOF
		../../nbd-server -C ${conffile} -p ${pidfile} &
		PID=$!
		sleep $DELAY
		./nbd-tester-client -N export1 -w -f localhost
		retval=$?
	;;
	*/dirconfig)
		# config.d-style configuration
		cat >${conffile} <<EOF
[generic]
	includedir = $tmpdir/confdir
EOF
		mkdir $tmpdir/confdir
		cat >$tmpdir/confdir/exp1.conf <<EOF
[export1]
	exportname = $tmpnam
EOF
		../../nbd-server -C ${conffile} -p ${pidfile} &
		PID=$!
		sleep $DELAY
		./nbd-tester-client -N export1 localhost
		retval=$?
	;;
	*/integrity)
		# Integrity test
		cat >${conffile} <<EOF
[generic]
[export1]
	exportname = $tmpnam
	flush = true
	fua = true
	rotational = true
	filesize = 52428800
	temporary = true
EOF
		../../nbd-server -C ${conffile} -p ${pidfile} &
		PID=$!
		sleep $DELAY
		./nbd-tester-client -N export1 -i -t ${mydir}/integrity-test.tr localhost
		retval=$?
	;;
	*/integrityhuge)
		# Integrity test
		cat >${conffile} <<EOF
[generic]
[export1]
	exportname = $tmpnam
	flush = true
	fua = true
	rotational = true
	filesize = 52428800
	temporary = true
EOF
		../../nbd-server -C ${conffile} -p ${pidfile} &
		PID=$!
		sleep $DELAY
		./nbd-tester-client -N export1 -i -t ${mydir}/integrityhuge-test.tr localhost
		retval=$?
	;;
	*/list)
		# List exports
		# This only works if we built nbd-client, which only exists on
		# Linux. But hey, testing nbd-client itself isn't a bad idea,
		# so here goes.
		if [ `uname -s` != "Linux" ]
		then
			retval=77
		else
			cat >${conffile} <<EOF
[generic]
	listenaddr = 127.0.0.1
	allowlist = true
[export1]
	exportname = $tmpnam
	readonly = true
EOF
			../../nbd-server -C ${conffile} -p ${pidfile} &
			PID=$!
			sleep $DELAY
			../../nbd-client -l localhost
			./nbd-tester-client -N export1 localhost
			retval=$?
		fi
		;;
	*/rowrite)
		cat >${conffile} <<EOF
[generic]
	listenaddr = 127.0.0.1
[export1]
	exportname = $tmpnam
	readonly = true
EOF
		../../nbd-server -C ${conffile} -p ${pidfile} &
		PID=$!
		sleep $DELAY
		./nbd-tester-client -N export1 -w -F localhost
		retval=$?
		;;
	*/unix)
		cat >${conffile} <<EOF
[generic]
	unixsock = ${tmpdir}/unix.sock
	listenaddr = 127.0.0.1
[export1]
	exportname = ${tmpnam}
EOF
		../../nbd-server -C ${conffile} -p ${pidfile} &
		PID=$!
		sleep $DELAY
		./nbd-tester-client -N export1 -u ${tmpdir}/unix.sock
		retval=$?
		;;
	*/inetd)
		cat >${conffile} <<EOF
[generic]
	port = 0
[export1]
	exportname = ${tmpnam}
EOF
		./nbd-tester-client -N export1 -I -- ../../nbd-server -d -C ${conffile}
		retval=$?
		;;
	*/handshake)
		# Test negotiation handshake
		cat >${conffile} <<EOF
[generic]
[export1]
	exportname = $tmpnam
EOF
		../../nbd-server -C ${conffile} -p ${pidfile} &
		PID=$!
		sleep $DELAY
		./nbd-tester-client -h -N export1 localhost
		retval=$?
	;;
	*/tls)
		# TLS test
		cat >${conffile} <<EOF
[generic]
	certfile = $certdir/server-cert.pem
	keyfile = $certdir/server-key.pem
	cacertfile = $certdir/ca-cert.pem
[export1]
	exportname = $tmpnam
	flush = true
	fua = true
	rotational = true
	filesize = 52428800
	temporary = true
EOF
		../../nbd-server -C ${conffile} -p ${pidfile} &
		PID=$!
		sleep $DELAY
		./nbd-tester-client -N export1 -i -t "${mydir}/integrity-test.tr" -C "${certdir}/client-cert.pem" -K "${certdir}/client-key.pem" -A "${certdir}/ca-cert.pem" localhost
		retval=$?
	;;
	*/tlshuge)
		# TLS test with big operations
		# takes a while
		cat >${conffile} <<EOF
[generic]
	certfile = $certdir/server-cert.pem
	keyfile = $certdir/server-key.pem
	cacertfile = $certdir/ca-cert.pem
[export1]
	exportname = $tmpnam
	flush = true
	fua = true
	rotational = true
	filesize = 52428800
	temporary = true
EOF
		../../nbd-server -C ${conffile} -p ${pidfile} &
		PID=$!
		sleep $DELAY
		./nbd-tester-client -N export1 -i -t "${mydir}/integrityhuge-test.tr" -C "${certdir}/client-cert.pem" -K "${certdir}/client-key.pem" -A "${certdir}/ca-cert.pem" -H localhost 127.0.0.1
		retval=$?
	;;
	*/tlswrongcert)
		cat >${conffile} <<EOF
[generic]
	certfile = $certdir/server-cert.pem
	keyfile = $certdir/server-key.pem
	cacertfile = $certdir/ca-cert.pem
[export1]
	exportname = $tmpnam
	flush = true
	fua = true
	rotational = true
	filesize = 52428800
	temporary = true
EOF
		../../nbd-server -C ${conffile} -p ${pidfile} &
		PID=$!
		sleep $DELAY
		./nbd-tester-client -N export1 -t "${mydir}/integrity-test.tr" -C "${certdir}/selfsigned-cert.pem" -K "${certdir}/selfsigned-key.pem" -F localhost
		retval=$?
	;;
	*)
		echo "E: unknown test $1"
		exit 1
	;;
esac

if [ $retval -ne 0 ]
then
	exit $retval
fi
